#include <framework/framework_i.h>

/* For the naive mapping strategy */
#define PADDR(kva) ((physaddr_t)(kva) - KBASE)
#define KADDR(pa)  (void *)((pa) + KBASE)

volatile struct ekf_sysconf_s ekf_sysconf;
volatile struct sysconf_s sysconf;

static int
uniprocessor_init(void)
{
	 /* Default to use PIC */
	 ekf_sysconf.has_pic = 1;
	 ekf_sysconf.use_pic = 1;

	 /* Without lapic and ioapic */
	 ekf_sysconf.ioapic_count = 0;
	 ekf_sysconf.use_ioapic   = 0;
	 ekf_sysconf.lcpu_count   = 1;
	 ekf_sysconf.use_lapic    = 0;
	 ekf_sysconf.lapic_phys   = 0;

	 apic_map[0] = 0;
}

int
sys_init(void)
{
	 kprintf("\n");
	 int err;

	 memset((void *)&ekf_sysconf, 0, sizeof(ekf_sysconf));
	 memset((void *)&sysconf, 0, sizeof(sysconf));
	 
	 /* Assume that we have pic */
	 ekf_sysconf.has_pic = 1;
	 smbios_init();
	 
	 if ((err = acpi_init()) < 0)
	 {
		  kprintf("ACPI error, consider initialized as uniprocessor\n");
		  err = uniprocessor_init();
	 }
	 else if (1 || ekf_sysconf.lcpu_count == 0)
	 {
		  kprintf("No LCPU found, consider initialized as uniprocessor\n");
		  err = uniprocessor_init();
	 }
	 else
	 {
		  if (ekf_sysconf.ioapic_count > 0)
		  {
		  	   ekf_sysconf.use_ioapic = 1;
		  }
		  else
		  {
			   ekf_sysconf.use_pic = 1;
		  }
		  
		  ekf_sysconf.use_lapic = 1;
	 }
	 
	 kprintf("PIC: %s, IOAPIC(%d): %s, LCPUs: %d, LAPIC: %s\n",
			 ekf_sysconf.use_pic ? "enabled" : "disabled",
			 ekf_sysconf.ioapic_count,
			 ekf_sysconf.use_ioapic ? "enabled" : "disabled",
			 ekf_sysconf.lcpu_count,
			 ekf_sysconf.use_lapic ? "enabled" : "disabled");
	 return err;
}

int
sys_post_fix(void)
{
	 /* Set the sysconf from ekf_sysconf */
	 sysconf.use_pic	= ekf_sysconf.use_pic;
	 sysconf.use_lapic	= ekf_sysconf.use_lapic;
	 sysconf.use_ioapic = ekf_sysconf.use_ioapic;
	 sysconf.lcpu_boot	= ekf_sysconf.lcpu_boot;
	 sysconf.lcpu_count = ekf_sysconf.lcpu_count;
	 sysconf.has_hpet	= ekf_sysconf.has_hpet;
	 sysconf.hpet_phys	= ekf_sysconf.hpet_phys;
	 sysconf.jiffies_0	= 0;

	 int i;

	 int ret = pmem_page_alloc(RM_IMAGE_PAGES, (physaddr_t *)&sysconf.rm_image_phys, 0, PPAGE_MANAGED);
	 if (ret < 0) return ret;
	 
	 for (i = 0; i != RM_IMAGE_PAGES; ++ i)
	 {
		  physaddr_t src = i << PAGE_SHIFT;
		  physaddr_t dst = sysconf.rm_image_phys + src;

		  char *dst_page;
		  BEGIN_TPAGE(dst, dst_page);

		  memmove(dst_page, KADDR(src), PAGE_SIZE);
		  
		  END_TPAGE;
	 }

	 return 0;
}
